import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
/*********************************************************************
 * Copyright (C) 2008 by Duncan A. Buell.  All rights reserved.
 * Class to read in letters for a Jumble puzzle and generate the
 * possible words.
 *
 * @author Duncan A. Buell
 * @version 1.00 2008-12-21
**/
public class SpellChecker
{
/*********************************************************************
 * Instance variables for this class.
**/
  private static final String classLabel = "Speller: ";
  private ArrayList<String> letters;
  private int numberOfPerms;		//number of permuatations that start with a letter
  private static HashSet<String> dictionary= new HashSet<String>();

/*********************************************************************
 * Constructor.
**/
  public SpellChecker()
  {
    this.letters = new ArrayList<String>();
    numberOfPerms=0;
  } // public Jumble2()

/*********************************************************************
 * Accessors and mutators.
**/
/*********************************************************************
 * Accessor for the <code>letters</code>.
**/
  //returns the number of permutations that start with a letter
  public int getNumberOfPerms(){
	  return numberOfPerms; 
  }
  public ArrayList<String> getLetters()
  {
    return this.letters;
  } // public ArrayList<String> getLetters()

/*********************************************************************
 * Accessor for the <code>size()</code>.
**/
  public int getSize()
  {
    return this.letters.size();
  } // public int getSize()

/*********************************************************************
 * General methods.
**/
/*********************************************************************
 * Method to generate the permutations of the <code>letters</code>.
 *
 * Generating permutations is slightly delicate, because we need
 * to "undo" as we return up the calling tower some of the context 
 * of the program we used in deeper calls.  Specifically,
 *
 * A) If we have no more letters in our list, we are done, and we
 *       print out the permutation.
 *
 * B)  Else run a loop on i on the letters in the current list.
 *   1a)  Copy the current list as passed in to a new current list
 *        to be passed recursively to this method.
 *   1a)  Get the i-th letter in the new list.
 *   1b)  Add the i-th letter to the end of the current perm.
 *   1c)  Remove the i-th letter from the new list.
 *
 *   2)   Call this method recursively, passing in the current perm
 *        and the new list of unuused letters.g in the current perm
 *
 *   3)   When the program returns from the recursion, take off
 *        the last letter of the current perm in preparation for the
 *        next iteration in the loop on i.
**/
  public void generatePermutations(ArrayList<String> thePerm,
                                   ArrayList<String> currentLetters)
  {
    String letter = "";
//    FileUtils.logFile.printf("%s enter generatePermutations %s %s%n",
//                             classLabel, thePerm, currentLetters);

    if(0 == currentLetters.size())
    {
    	//increments the number of permuatations
    	numberOfPerms++;
    	
    	//creates a string version of the array of characters, used to see if it is a word or not
    	String s="";
    	for(int i=0; i<thePerm.size(); i++){
    		s+=thePerm.get(i);
    	}
    
      
    
    	  
    	 
    		
    
    		  	//checks to see if the permutation is a word and prints an appropriate message
    		  if(dictionary.contains(s)){
    			  FileUtils.logFile.printf("%s perm is '%s'%n", classLabel, thePerm);
    	          FileUtils.logFile.flush();
    		  }
    		  else{
    				FileUtils.logFile.printf("%s BAD WORD  '%s'%n", classLabel, thePerm);
    	    		FileUtils.logFile.flush();
    		  }
    		
    	  
    	  //}
    	  
    }
    else
    {
      for(int i = 0; i < currentLetters.size(); ++i)
      {
    	  
        // create a new instance of an arraylist for passing in,
        // and violate our rules on variable declaration to
        // emphasize that we absolutely need a new instance
        ArrayList<String> newLetters = new ArrayList<String>();
        for(int j = 0; j < currentLetters.size(); ++j){
        	//Character isLetter=new Character(currentLetters.get(i).charAt(0))
        	if(Character.isLetter(currentLetters.get(j).charAt(0))){
        		currentLetters.set(j, currentLetters.get(j).toLowerCase());
        		newLetters.add(currentLetters.get(j));
        	}
        	else{
        		currentLetters.remove(j);
        	}
         
          
        }
    
        
        letter = currentLetters.get(i);
      
        thePerm.add(letter);
        newLetters.remove(i);
           
        //checks to see if the first letter of the permuation is not a letter and removes it if it is
           Character theLetter= new Character(thePerm.get(0).charAt(0));
           if(!Character.isLetter(theLetter)){
        	   thePerm.remove(0);
        	   
           }
           else{ 
        	
        /*FileUtils.logFile.printf("%s next,word,newLetters %s %s %s%n", classLabel, letter,
                                 thePerm, newLetters);
        FileUtils.logFile.flush();*/
        	   
        generatePermutations(thePerm, newLetters);
        thePerm.remove(thePerm.size()-1);
        
       }
        
      
      }
    }

//    FileUtils.logFile.printf("%s leave generatePermutations%n",classLabel);
  } // public void generatePermutations()

/*********************************************************************
 * Method to read the <code>Jumble</code> data from an input
 * <code>Scanner</code> file. Note that this is more or less hard coded.
 * Also that we don't bulletproof the input; among other things we
 * assume that partial records don't appear in the input data.
 *
 * @param the <code>Scanner</code> from which to read.
**/
  public SpellChecker readCharacters(Scanner inFile)
  {
    int subscript = 0;
    String s;
    SpellChecker newJumble = null;
    
    newJumble = new SpellChecker();
    subscript = -1;
    while(inFile.hasNext())
    {
      s = inFile.next();
      ++subscript;
      newJumble.letters.add(s);
    }

    return newJumble;
  } // public Jumble readJumble(Scanner inFile)
  
  
  
  //method to read from the dictionary file and add it to the hashSet
  public void readDictionary(String fileName) throws FileNotFoundException{
	  File dict=new File(fileName);
	  Scanner inFile=new Scanner(dict);
	  while(inFile.hasNext()){
		  dictionary.add(inFile.next());
	  }
	  
  }

  
  
  
  
  
  

/*********************************************************************
 * Method to <code>toString</code> the set of letters for a Jumble.
 *
 * @return the <code>toString</code> rep'n of the letters.
**/
  public String toString()
  {
    String s = "";
    for(int i = 0; i < this.letters.size(); ++i)
    {
      s += this.letters.get(i);
    }
    return s;
  } // public String toString()

} // public class Jumble
